home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / gnu / gnpltsrc.lha / gplt_x11.c < prev    next >
C/C++ Source or Header  |  1996-01-22  |  33KB  |  1,027 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: gplt_x11.c,v 1.46 1995/11/20 11:24:12 drd Exp $";
  3. #endif
  4.  
  5.  
  6. /*-----------------------------------------------------------------------------
  7.  *   gnuplot_x11 - X11 outboard terminal driver for gnuplot 3.3
  8.  *
  9.  *   Requires installation of companion inboard x11 driver in gnuplot/term.c
  10.  *
  11.  *   Acknowledgements: 
  12.  *      Chris Peterson (MIT)
  13.  *      Dana Chee (Bellcore) 
  14.  *      Arthur Smith (Cornell)
  15.  *      Hendri Hondorp (University of Twente, The Netherlands)
  16.  *      Bill Kucharski (Solbourne)
  17.  *      Charlie Kline (University of Illinois)
  18.  *      Yehavi Bourvine (Hebrew University of Jerusalem, Israel)
  19.  *      Russell Lang (Monash University, Australia)
  20.  *      O'Reilly & Associates: X Window System - Volumes 1 & 2
  21.  *
  22.  *   This code is provided as is and with no warranties of any kind.
  23.  *       
  24.  * There is a mailing list for gnuplot users. Note, however, that the
  25.  * newsgroup 
  26.  *    comp.graphics.gnuplot 
  27.  * is identical to the mailing list (they
  28.  * both carry the same set of messages). We prefer that you read the
  29.  * messages through that newsgroup, to subscribing to the mailing list.
  30.  * (If you can read that newsgroup, and are already on the mailing list,
  31.  * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  32.  * removed from the mailing list.)
  33.  *
  34.  * The address for mailing to list members is
  35.  *       info-gnuplot@dartmouth.edu
  36.  * and for mailing administrative requests is 
  37.  *       info-gnuplot-request@dartmouth.edu
  38.  * The mailing list for bug reports is 
  39.  *       bug-gnuplot@dartmouth.edu
  40.  * The list of those interested in beta-test versions is
  41.  *       info-gnuplot-beta@dartmouth.edu
  42.  *---------------------------------------------------------------------------*/
  43.  
  44. #define DEFAULT_X11
  45. #if defined(VMS) || defined(CRIPPLED_SELECT)
  46. #undef DEFAULT_X11
  47. #endif
  48. #if defined(VMS) && defined(CRIPPLED_SELECT)
  49. Error. Incompatible options.
  50. #endif
  51.  
  52. #include <X11/Xos.h>
  53. #include <X11/Xlib.h>
  54. #include <X11/Xutil.h>
  55. #include <X11/Xatom.h>
  56. #include <X11/Xresource.h>
  57.  
  58. #include <stdio.h>
  59. #include <signal.h>
  60. #include "stdfn.h"
  61.  
  62. #ifdef BSD_TYPES
  63. #include <sys/bsdtypes.h>
  64. #endif /* BSD_TYPES */
  65.  
  66. #if !defined(VMS) && !defined(FD_SET) && !defined(OLD_SELECT)
  67. #include <sys/select.h>
  68. #endif /* !VMS && !FD_SET && !OLD_SELECT */
  69.  
  70. #ifndef FD_SET
  71.  
  72. #define FD_SET(n, p)    ((p)->fds_bits[0] |= (1 << ((n) % 32)))
  73. #define FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1 << ((n) % 32)))
  74. #define FD_ISSET(n, p)  ((p)->fds_bits[0] & (1 << ((n) % 32)))
  75. #define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
  76.  
  77. #endif /* !FD_SET */
  78.  
  79. #ifdef SOLARIS
  80. #include <sys/systeminfo.h>
  81. #endif /* SOLARIS */
  82.  
  83.  
  84. #include <errno.h>
  85. extern int errno;
  86.  
  87. #ifdef OSK
  88. #define EINTR    E_ILLFNC
  89. #endif
  90.  
  91. #include "ansichek.h"
  92.  
  93. int main __P((int argc,  char *argv[]));
  94. void mainloop __P((void));
  95. int record __P((void));
  96. void display __P((void));
  97. int resize __P((XConfigureEvent *xce));
  98. void preset __P((int argc, char *argv[]));
  99. char *pr_GetR __P((XrmDatabase db, char *resource));
  100. void pr_color __P((void));
  101. void pr_dashes __P((void));
  102. void pr_font __P((void));
  103. void pr_geometry __P((void));
  104. void pr_pointsize __P((void));
  105. void pr_width __P((void));
  106. void pr_window __P((void));
  107.  
  108. #define FallbackFont "fixed"
  109.  
  110. #define Ncolors 13
  111. unsigned long colors[Ncolors];
  112.  
  113. #define Nwidths 10
  114. unsigned int widths[Nwidths] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  115.  
  116. #define Ndashes 10
  117. char dashes[Ndashes][5];
  118.  
  119. Display *dpy; int scr; Window win, root;
  120. Visual *vis; GC gc = (GC)0; Pixmap pixmap; XFontStruct *font;
  121. unsigned int W = 640, H = 450; int D, gX = 100, gY = 100;
  122. unsigned int BorderWidth = 2;
  123. unsigned User_Size = 0, User_Position = 0; /* User specified? */
  124.  
  125.  
  126. Bool Mono = 0, Gray = 0, Rv = 0, Clear = 0;
  127. char Name[64] = "gnuplot";
  128. char Class[64] = "Gnuplot";
  129.  
  130. int cx=0, cy=0, vchar, nc = 0, ncalloc = 0;
  131. double xscale, yscale, pointsize;
  132. #define X(x) (int) (x * xscale)
  133. #define Y(y) (int) ((4095-y) * yscale)
  134. enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
  135.  
  136. #define Nbuf 1024
  137. char buf[Nbuf], **commands = (char **)0;
  138.  
  139. FILE *X11_ipc;
  140. char X11_ipcpath[32];
  141.  
  142.  
  143. /*-----------------------------------------------------------------------------
  144.  *   main program 
  145.  *---------------------------------------------------------------------------*/
  146.  
  147. int main(argc, argv) int argc; char *argv[]; {
  148.  
  149. #ifdef OSK    /* malloc large blocks, otherwise problems with fragmented mem */
  150.    _mallocmin (102400);
  151. #endif
  152.    preset(argc, argv);
  153.    mainloop();
  154.    exit(0);
  155.    return 0;
  156.    }
  157.  
  158. /*-----------------------------------------------------------------------------
  159.  *   mainloop processing - process X events and input from gnuplot
  160.  *
  161.  *   Three different versions of main loop processing are provided to support
  162.  *   three different platforms.
  163.  * 
  164.  *   DEFAULT_X11:     use select() for both X events and input on stdin 
  165.  *                    from gnuplot inboard driver
  166.  *
  167.  *   CRIPPLED_SELECT: use select() to service X events and check during 
  168.  *                    select timeout for temporary plot file created
  169.  *                    by inboard driver
  170.  *
  171.  *   VMS:             use XNextEvent to service X events and AST to
  172.  *                    service input from gnuplot inboard driver on stdin 
  173.  *---------------------------------------------------------------------------*/
  174.  
  175.  
  176. #ifdef DEFAULT_X11
  177. /*-----------------------------------------------------------------------------
  178.  *    DEFAULT_X11 mainloop
  179.  *---------------------------------------------------------------------------*/
  180.  
  181. void mainloop() {
  182.    int nf, nfds, cn = ConnectionNumber(dpy), in;
  183.    struct timeval timeout, *timer = (struct timeval *)0;
  184.    fd_set rset, tset;
  185.    unsigned long all = 0xffffffff;
  186.    XEvent xe;
  187.  
  188.    X11_ipc = stdin;
  189.    in = fileno (X11_ipc);
  190.  
  191.    FD_ZERO(&rset);
  192.    FD_SET(cn, &rset);
  193.  
  194.    FD_SET(in, &rset);
  195.    nfds = (cn > in) ? cn + 1 : in + 1;
  196.  
  197. #ifdef ISC22
  198. /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  199.    timeout.tv_sec  = 0;        /* select() in ISC2.2 needs timeout */
  200.    timeout.tv_usec = 300000;    /* otherwise input from gnuplot is */
  201.    timer = &timeout;        /* suspended til next X event. */
  202. #endif /* ISC22      (0.3s are short enough not to be noticed */
  203.  
  204.    while(1) {
  205.       tset = rset;
  206. #if defined(__hpux) && defined(__STDC__)
  207.       nf = select(nfds, (int *)&tset, (int *)0, (int *)0, timer);
  208. #else
  209.       nf = select(nfds, &tset, (fd_set *)0, (fd_set *)0, timer);
  210. #endif
  211.       if (nf < 0) {
  212.      if (errno == EINTR) continue;
  213.      fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
  214.      exit(1);
  215.      }
  216.       if (nf > 0) XNoOp(dpy);
  217.       if (FD_ISSET(cn, &tset)) {
  218.      while (XCheckMaskEvent(dpy, all, &xe)) {
  219.         (xe.type == ConfigureNotify)  && resize((XConfigureEvent *)&xe); 
  220.         }
  221.      }
  222.       FD_ISSET(in, &tset) && record();
  223.       }
  224.    }
  225.  
  226. #endif
  227.  
  228.  
  229. #ifdef CRIPPLED_SELECT
  230. /*-----------------------------------------------------------------------------
  231.  *    CRIPPLED_SELECT mainloop
  232.  *---------------------------------------------------------------------------*/
  233.  
  234. void mainloop() {
  235.    int nf, nfds, cn = ConnectionNumber(dpy);
  236.    struct timeval timeout, *timer;
  237.    fd_set rset, tset;
  238.    unsigned long all = 0xffffffff;
  239.    XEvent xe;
  240.  
  241.    FD_ZERO(&rset);
  242.    FD_SET(cn, &rset);
  243.  
  244.    timeout.tv_sec = 1;
  245.    timeout.tv_usec = 0;
  246.    timer = &timeout;
  247.    sprintf(X11_ipcpath, "/tmp/Gnuplot_%d", getppid());
  248.    nfds = cn + 1;
  249.  
  250.    while(1) {
  251.       tset = rset;
  252.       nf = select(nfds, &tset, (fd_set *)0, (fd_set *)0, timer);
  253.       if (nf < 0) {
  254.      if (errno == EINTR) continue;
  255.      fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
  256.      exit(1);
  257.      }
  258.       nf > 0 && XNoOp(dpy);
  259.       if (FD_ISSET(cn, &tset)) {
  260.      while (XCheckMaskEvent(dpy, all, &xe)) {
  261.         (xe.type == ConfigureNotify)  && resize((XConfigureEvent *)&xe); 
  262.         }
  263.      }
  264.       if ((X11_ipc = fopen(X11_ipcpath, "r"))) {
  265.      unlink(X11_ipcpath);
  266.      record();
  267.      fclose(X11_ipc);
  268.      }
  269.       }
  270.    }
  271. #endif /* CRIPPLED_SELECT */
  272.  
  273.  
  274. #ifdef VMS
  275. /*-----------------------------------------------------------------------------
  276.  *    VMS mainloop - Yehavi Bourvine - YEHAVI@VMS.HUJI.AC.IL
  277.  *---------------------------------------------------------------------------*/
  278.  
  279. /*  In VMS there is no decent Select(). hence, we have to loop inside
  280.  *  XGetNextEvent for getting the next X window event. In order to get input
  281.  *  from the master we assign a channel to SYS$INPUT and use AST's in order to
  282.  *  receive data. */
  283.  
  284. #include <iodef.h>
  285. char    STDIIN[] = "SYS$INPUT:";
  286. short   STDIINchannel, STDIINiosb[4];
  287. struct  { short size, type; char  *address; } STDIINdesc;
  288. char    STDIINbuffer[64];
  289. int     status;
  290.  
  291.  
  292. void mainloop() {
  293.    XEvent xe;
  294.  
  295.    STDIINdesc.size = strlen(STDIIN); 
  296.    STDIINdesc.type = 0;
  297.    STDIINdesc.address = STDIIN;
  298.    status = sys$assign(&STDIINdesc, &STDIINchannel, 0, 0, 0);
  299.    if((status & 0x1) == 0)  exit(status); 
  300.    ast();
  301.  
  302.    for(;;) {
  303.       XNextEvent(dpy, &xe);
  304.       (xe.type == ConfigureNotify)  && resize((XConfigureEvent *)&xe); 
  305.       }
  306.    }
  307.  
  308. ast() {
  309.    int record();
  310.    int status = sys$qio(0, STDIINchannel, IO$_READVBLK, STDIINiosb, record,
  311.                 0, STDIINbuffer, sizeof(STDIINbuffer) -1,0, 0, 0, 0);
  312.    if((status & 0x1) == 0) exit(status);
  313.    }
  314. #endif /* VMS */
  315.  
  316.  
  317. #ifndef VMS
  318. /*-----------------------------------------------------------------------------
  319.  *   record - record new plot from gnuplot inboard X11 driver (Unix)
  320.  *---------------------------------------------------------------------------*/
  321.  
  322. record() {
  323.  
  324.    while (fgets(buf, Nbuf, X11_ipc)) {
  325.      if (*buf == 'G') {                           /* enter graphics mode */
  326.      if (commands) {
  327.         int n; for (n=0; n<nc; n++) free(commands[n]);
  328.         free(commands);
  329.         }
  330.      commands = (char **)0; nc = ncalloc = 0;
  331.          }
  332.       else if (*buf == 'E') { display(); break; } /* leave graphics mode */
  333.       else if (*buf == 'R') { exit(0); }          /* leave X11/x11 mode  */
  334.       else {                                      /* record command      */
  335.      char *p;
  336.      if (nc >= ncalloc) {
  337.         ncalloc = ncalloc*2 + 1;
  338.         commands = (commands)
  339.            ? (char **)realloc(commands, ncalloc * sizeof(char *))
  340.            : (char **)malloc(sizeof(char *));
  341.         }
  342.      p = (char *)malloc((unsigned)strlen(buf)+1);
  343.      if (!commands || !p) {
  344.         fprintf(stderr, "gnuplot: can't get memory. X11 aborted.\n");
  345.         exit(1);
  346.         }
  347.      commands[nc++] = strcpy(p, buf);
  348.      }
  349.       }
  350. #ifdef OSK
  351.    if (feof(X11_ipc))      /* On OS-9 sometimes while resizing the window,  */
  352.       _cleareof (X11_ipc); /* and plotting data, the eof or error flag of   */
  353.    if (ferror(X11_ipc))    /* X11_ipc stream gets set, while there is       */
  354.          clearerr (X11_ipc);  /* nothing wrong! Probably a bug in my select()? */
  355. #else
  356.    if (feof(X11_ipc) || ferror(X11_ipc)) exit(1);
  357. #endif
  358.    }
  359.  
  360. #else    /* VMS */
  361. /*-----------------------------------------------------------------------------
  362.  *   record - record new plot from gnuplot inboard X11 driver (VMS)
  363.  *---------------------------------------------------------------------------*/
  364.  
  365. record() {
  366.    int    status;
  367.  
  368.    if((STDIINiosb[0] & 0x1) == 0) exit(STDIINiosb[0]);
  369.    STDIINbuffer[STDIINiosb[1]] = '\0';
  370.    strcpy(buf, STDIINbuffer);
  371.  
  372.    if (*buf == 'G') {                           /* enter graphics mode */
  373.       if (commands) {
  374.          int n; for (n=0; n<nc; n++) free(commands[n]);
  375.          free(commands);
  376.          }
  377.        commands = (char **)0; nc = ncalloc = 0;
  378.        }
  379.    else if (*buf == 'E') {                      /* leave graphics mode */
  380.       display(); 
  381.       }
  382.    else if (*buf == 'R') {                      /* leave x11/X11 mode  */
  383.        sys$cancel(STDIINchannel);
  384.        XCloseDisplay(dpy);
  385.        sys$delprc(0,0);      /* Somehow it doesn't drop itself... */
  386.        exit(1); 
  387.        }
  388.    else {                                       /* record command      */
  389.       char *p;
  390.       if (nc >= ncalloc) {
  391.      ncalloc = ncalloc*2 + 1;
  392.      commands = (commands)
  393.         ? (char **)realloc(commands, ncalloc * sizeof(char *))
  394.         : (char **)malloc(sizeof(char *));
  395.      }
  396.       p = (char *)malloc((unsigned)strlen(buf)+1);
  397.       if (!commands || !p) {
  398.      fprintf(stderr, "gnuplot: can't get memory. X11 aborted.\n");
  399.      exit(1);
  400.      }
  401.       commands[nc++] = strcpy(p, buf);
  402.       }
  403.    ast();
  404.    }
  405. #endif /* VMS */
  406.  
  407. /*-----------------------------------------------------------------------------
  408.  *   display - display last plot from gnuplot inboard X11 driver
  409.  *---------------------------------------------------------------------------*/
  410.  
  411. void display() {
  412.    int n, x, y, sw, sl, lt, width, type, point, px, py;
  413.    char *buf, *str;
  414.  
  415.    if (!nc) return;
  416.  
  417.    /* set scaling factor between internal driver & window geometry */
  418.    xscale = (double)W / 4096.;  yscale = (double)H / 4096.;  
  419.  
  420.    /* create new pixmap & GC */
  421.    if (gc) { XFreeGC(dpy, gc); XFreePixmap(dpy, pixmap); }
  422.    pixmap = XCreatePixmap(dpy, root, W, H, D);
  423.    gc = XCreateGC(dpy, pixmap, 0, (XGCValues *)0);
  424.    XSetFont(dpy, gc, font->fid);
  425.  
  426.    /* set pixmap background */
  427.    XSetForeground(dpy, gc, colors[0]);
  428.    XFillRectangle(dpy, pixmap, gc, 0, 0, W, H);
  429.    XSetBackground(dpy, gc, colors[0]);
  430.  
  431.    /* top the window but don't put keyboard or mouse focus into it. */
  432.    XMapRaised(dpy, win);
  433.  
  434.    /* momentarily clear the window first if requested */
  435.    if (Clear) {
  436.       XClearWindow(dpy, win);
  437.       XFlush(dpy);
  438.       }
  439.  
  440.    /* loop over accumulated commands from inboard driver */
  441.    for (n=0; n<nc; n++) {
  442.       buf = commands[n];
  443.  
  444.       /*   X11_vector(x,y) - draw vector  */
  445.       if (*buf == 'V') { 
  446.      sscanf(buf, "V%4d%4d", &x, &y);  
  447.      XDrawLine(dpy, pixmap, gc, X(cx), Y(cy), X(x), Y(y));
  448.      cx = x; cy = y;
  449.      }
  450.  
  451.       /*   X11_move(x,y) - move  */
  452.       else if (*buf == 'M') 
  453.      sscanf(buf, "M%4d%4d", &cx, &cy);  
  454.  
  455.       /*   X11_put_text(x,y,str) - draw text   */
  456.       else if (*buf == 'T') { 
  457.      sscanf(buf, "T%4d%4d", &x, &y);  
  458.      str = buf + 9; sl = strlen(str) - 1;
  459.      sw = XTextWidth(font, str, sl);
  460.      switch(jmode) {
  461.         case LEFT:   sw = 0;     break;
  462.         case CENTRE: sw = -sw/2; break;
  463.         case RIGHT:  sw = -sw;   break;
  464.         }
  465.      XSetForeground(dpy, gc, colors[2]);
  466.      XDrawString(dpy, pixmap, gc, X(x)+sw, Y(y)+vchar/3, str, sl);
  467.      XSetForeground(dpy, gc, colors[lt+3]);
  468.      }
  469.  
  470.       /*   X11_justify_text(mode) - set text justification mode  */
  471.       else if (*buf == 'J') 
  472.      sscanf(buf, "J%4d", &jmode);
  473.  
  474.       /*   X11_linetype(type) - set line type  */
  475.       else if (*buf == 'L') { 
  476.      sscanf(buf, "L%4d", <);
  477.      lt = (lt%8)+2;
  478.      width = widths[lt];
  479.      if (dashes[lt][0]) {
  480.         type = LineOnOffDash;
  481.         XSetDashes(dpy, gc, 0, dashes[lt], strlen(dashes[lt]));
  482.         }
  483.      else {
  484.         type = LineSolid;
  485.         }
  486.      XSetForeground(dpy, gc, colors[lt+3]);
  487.      XSetLineAttributes( dpy,gc, width, type, CapButt, JoinBevel);
  488.        }
  489.  
  490.       /*   X11_point(number) - draw a point */
  491.       else if (*buf == 'P') { 
  492.       sscanf(buf, "P%1d%4d%4d", &point, &x, &y);  
  493.       if (point==7) {
  494.          /* set point size */
  495.          px = (int) (x * xscale * pointsize);
  496.          py = (int) (y * yscale * pointsize);
  497.          }
  498.       else {
  499.         if (type != LineSolid || width != 0) {  /* select solid line */
  500.            XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinBevel);
  501.            }
  502.         switch(point) {
  503.            case 0: /* dot */
  504.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  505.            break;
  506.            case 1: /* do diamond */ 
  507.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x), Y(y)-py);
  508.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x)+px, Y(y));
  509.            XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y), X(x), Y(y)+py);
  510.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)+py, X(x)-px, Y(y));
  511.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  512.            break;
  513.            case 2: /* do plus */ 
  514.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x)+px, Y(y));
  515.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x), Y(y)+py);
  516.            break;
  517.            case 3: /* do box */ 
  518.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)-py);
  519.            XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y)-py, X(x)+px, Y(y)+py);
  520.            XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y)+py, X(x)-px, Y(y)+py);
  521.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)-px, Y(y)-py);
  522.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  523.            break;
  524.            case 4: /* do X */ 
  525.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)+py);
  526.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)+px, Y(y)-py);
  527.            break;
  528.            case 5: /* do triangle */ 
  529.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-(4*px/3), 
  530.                  X(x)-(4*px/3), Y(y)+(2*py/3));
  531.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-(4*px/3), 
  532.                  X(x)+(4*px/3), Y(y)+(2*py/3));
  533.            XDrawLine(dpy,pixmap,gc, X(x)-(4*px/3), Y(y)+(2*py/3), 
  534.                  X(x)+(4*px/3), Y(y)+(2*py/3));
  535.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  536.            break;
  537.            case 6: /* do star */ 
  538.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x)+px, Y(y));
  539.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x), Y(y)+py);
  540.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)+py);
  541.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)+px, Y(y)-py);
  542.            break;
  543.            }
  544.         if (type != LineSolid || width != 0) {  /* select solid line */
  545.            XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
  546.            }
  547.         }
  548.      }
  549.       }
  550.  
  551.    /* set new pixmap as window background */
  552.    XSetWindowBackgroundPixmap(dpy, win, pixmap);
  553.  
  554.    /* trigger exposure of background pixmap */
  555.    XClearWindow(dpy,win);
  556.    XFlush(dpy);
  557.    }
  558.  
  559. /*-----------------------------------------------------------------------------
  560.  *   resize - rescale last plot if window resized
  561.  *---------------------------------------------------------------------------*/
  562.  
  563. resize(xce) XConfigureEvent *xce; {
  564.    int w = xce->width, h = xce->height;
  565.    
  566.    if (w>1 && h>1 && (w != W || h != H)) {
  567.       W = w; H = h;
  568.       display();
  569.       }
  570.    }
  571.  
  572.  
  573. /*-----------------------------------------------------------------------------
  574.  *   preset - determine options, open display, create window
  575.  *---------------------------------------------------------------------------*/
  576.  
  577. #define On(v) ( !strcmp(v,"on") || !strcmp(v,"true") || \
  578.                 !strcmp(v,"On") || !strcmp(v,"True") || \
  579.                 !strcmp(v,"ON") || !strcmp(v,"TRUE") )
  580.  
  581. #define AppDefDir "/usr/lib/X11/app-defaults"
  582. #ifndef MAXHOSTNAMELEN
  583. #define MAXHOSTNAMELEN 64
  584. #endif
  585.  
  586. static XrmDatabase dbCmd, dbApp, dbDef, dbEnv, db = (XrmDatabase)0;
  587.  
  588. char *pr_GetR(), *getenv(), *type[20];
  589. XrmValue value;
  590.  
  591. #define Nopt 27
  592. static XrmOptionDescRec options[] = {
  593.    {"-mono",             ".mono",             XrmoptionNoArg,   (caddr_t) "on" },
  594.    {"-gray",             ".gray",             XrmoptionNoArg,   (caddr_t) "on" },
  595.    {"-clear",            ".clear",            XrmoptionNoArg,   (caddr_t) "on" },
  596.    {"-tvtwm",            ".tvtwm",            XrmoptionNoArg,   (caddr_t) "on" },
  597.    {"-pointsize",        ".pointsize",        XrmoptionSepArg,  (caddr_t) NULL },
  598.    {"-display",          ".display",          XrmoptionSepArg,  (caddr_t) NULL },
  599.    {"-name",             ".name",             XrmoptionSepArg,  (caddr_t) NULL },
  600.    {"-geometry",         "*geometry",         XrmoptionSepArg,  (caddr_t) NULL },
  601.    {"-background",       "*background",       XrmoptionSepArg,  (caddr_t) NULL },
  602.    {"-bg",               "*background",       XrmoptionSepArg,  (caddr_t) NULL },
  603.    {"-foreground",       "*foreground",       XrmoptionSepArg,  (caddr_t) NULL },
  604.    {"-fg",               "*foreground",       XrmoptionSepArg,  (caddr_t) NULL },
  605.    {"-bordercolor",      "*bordercolor",      XrmoptionSepArg,  (caddr_t) NULL },
  606.    {"-bd",               "*bordercolor",      XrmoptionSepArg,  (caddr_t) NULL },
  607.    {"-borderwidth",      ".borderwidth",      XrmoptionSepArg,  (caddr_t) NULL },
  608.    {"-bw",               ".borderwidth",      XrmoptionSepArg,  (caddr_t) NULL },
  609.    {"-font",             "*font",             XrmoptionSepArg,  (caddr_t) NULL },
  610.    {"-fn",               "*font",             XrmoptionSepArg,  (caddr_t) NULL },
  611.    {"-reverse",          "*reverseVideo",     XrmoptionNoArg,   (caddr_t) "on" },
  612.    {"-rv",               "*reverseVideo",     XrmoptionNoArg,   (caddr_t) "on" },
  613.    {"+rv",               "*reverseVideo",     XrmoptionNoArg,   (caddr_t) "off"},
  614.    {"-iconic",           "*iconic",           XrmoptionNoArg,   (caddr_t) "on" },
  615.    {"-synchronous",      "*synchronous",      XrmoptionNoArg,   (caddr_t) "on" },
  616.    {"-xnllanguage",      "*xnllanguage",      XrmoptionSepArg,  (caddr_t) NULL },
  617.    {"-selectionTimeout", "*selectionTimeout", XrmoptionSepArg,  (caddr_t) NULL },
  618.    {"-title",            ".title",            XrmoptionSepArg,  (caddr_t) NULL },
  619.    {"-xrm",              NULL,                XrmoptionResArg,  (caddr_t) NULL },
  620.    };
  621.  
  622. void preset(argc, argv) int argc; char *argv[]; {
  623.    int Argc = argc; char **Argv = argv;
  624.  
  625. #ifdef VMS
  626.    char *display = (char *) 0;
  627. #else
  628.    char *display = getenv("DISPLAY");
  629. #endif
  630.    char *home = getenv("HOME");
  631.    char *server_defaults, *env, buf[256];
  632.  
  633.    /* avoid bus error when env vars are not set */
  634.    if(display==NULL) display="";
  635.    if(home==NULL) home="";
  636.  
  637.    /*---set to ignore ^C and ^Z----------------------------------------------*/
  638.  
  639.    signal(SIGINT, SIG_IGN);
  640. #ifdef SIGTSTP
  641.    signal(SIGTSTP, SIG_IGN);
  642. #endif
  643.  
  644.    /*---prescan arguments for "-name"----------------------------------------*/
  645.  
  646.    while(++Argv, --Argc > 0) {
  647.       if (!strcmp(*Argv, "-name") && Argc > 1) {
  648.      strncpy(Name, Argv[1], 64);
  649.      strncpy(Class, Argv[1], 64);
  650.      if (Class[0] >= 'a' && Class[0] <= 'z') Class[0] -= 0x20;
  651.      }
  652.       }
  653.    Argc = argc; Argv = argv;
  654.  
  655.    /*---parse command line---------------------------------------------------*/
  656.  
  657.    XrmInitialize();
  658.    XrmParseCommand(&dbCmd, options, Nopt, Name, &Argc, Argv);
  659.    if (Argc > 1) {
  660.       fprintf(stderr, "\ngnuplot: bad option: %s\n", Argv[1]);
  661.       fprintf(stderr, "gnuplot: X11 aborted.\n");
  662.       exit(1);
  663.       }
  664.    if (pr_GetR(dbCmd, ".display")) display = (char *) value.addr;
  665.  
  666.    /*---open display---------------------------------------------------------*/
  667.  
  668.    dpy = XOpenDisplay(display); 
  669.    if (!dpy) {
  670.       fprintf(stderr, "\ngnuplot: unable to open display '%s'\n", display);
  671.       fprintf(stderr, "gnuplot: X11 aborted.\n");
  672.       exit(1);
  673.       }
  674.    scr = DefaultScreen(dpy);
  675.    vis = DefaultVisual(dpy,scr);
  676.    D = DefaultDepth(dpy,scr);
  677.    root = DefaultRootWindow(dpy);
  678.    server_defaults = XResourceManagerString(dpy);
  679.  
  680.    /*---get application defaults--(subset of Xt processing)------------------*/
  681.  
  682. #ifdef VMS
  683.    strcpy (buf, "DECW$USER_DEFAULTS:GNUPLOT_X11.INI");
  684. #else
  685.    sprintf(buf, "%s/%s", AppDefDir, "Gnuplot");
  686. #endif
  687.    dbApp = XrmGetFileDatabase(buf);
  688.    XrmMergeDatabases(dbApp, &db);
  689.  
  690.    /*---get server or ~/.Xdefaults-------------------------------------------*/
  691.  
  692.    if (server_defaults)
  693.       dbDef = XrmGetStringDatabase(server_defaults);
  694.    else {
  695. #ifdef VMS
  696.       strcpy(buf,"DECW$USER_DEFAULTS:DECW$XDEFAULTS.DAT");
  697. #else
  698.       sprintf(buf, "%s/.Xdefaults", home);
  699. #endif
  700.       dbDef = XrmGetFileDatabase(buf);
  701.       }
  702.    XrmMergeDatabases(dbDef, &db);
  703.  
  704.    /*---get XENVIRONMENT or  ~/.Xdefaults-hostname---------------------------*/
  705.  
  706. #ifndef VMS
  707.    if (env = getenv("XENVIRONMENT")) 
  708.       dbEnv = XrmGetFileDatabase(env);
  709.    else {
  710.       char *p, host[MAXHOSTNAMELEN];
  711. #ifdef SOLARIS
  712.       if (sysinfo(SI_HOSTNAME, host, MAXHOSTNAMELEN) < 0) {
  713.          fprintf(stderr, "gnuplot: sysinfo failed. X11 aborted.\n");
  714. #else
  715.       if (gethostname(host, MAXHOSTNAMELEN) < 0) {
  716.          fprintf(stderr, "gnuplot: gethostname failed. X11 aborted.\n");
  717. #endif /* SOLARIS */
  718.      exit(1);
  719.      }
  720.       if (p = index(host, '.')) *p = '\0';
  721.       sprintf(buf, "%s/.Xdefaults-%s", home, host);
  722.       dbEnv = XrmGetFileDatabase(buf);
  723.       }
  724.    XrmMergeDatabases(dbEnv, &db);
  725. #endif   /* not VMS */
  726.  
  727.    /*---merge command line options-------------------------------------------*/
  728.  
  729.    XrmMergeDatabases(dbCmd, &db);
  730.  
  731.    /*---set geometry, font, colors, line widths, dash styles, point size-----*/
  732.  
  733.    pr_geometry();
  734.    pr_font();
  735.    pr_color();
  736.    pr_width();
  737.    pr_dashes();
  738.    pr_pointsize();
  739.  
  740.    /*---create window--------------------------------------------------------*/
  741.  
  742.    pr_window();
  743.  
  744.    } 
  745.  
  746. /*-----------------------------------------------------------------------------
  747.  *   pr_GetR - get resource from database using "-name" option (if any)
  748.  *---------------------------------------------------------------------------*/
  749.  
  750. char *
  751. pr_GetR(db, resource) XrmDatabase db; char *resource; {
  752.    char name[128], class[128], *rc;
  753.  
  754.    strcpy(name, Name); strcat(name, resource);
  755.    strcpy(class, Class); strcat(class, resource);
  756.    rc = XrmGetResource(db, name, class, type, &value)
  757.       ? (char *)value.addr 
  758.       : (char *)0;
  759.    return(rc);
  760.    }
  761.  
  762. /*-----------------------------------------------------------------------------
  763.  *   pr_color - determine color values
  764.  *---------------------------------------------------------------------------*/
  765.  
  766. char color_keys[Ncolors][30] =   { 
  767.    "background", "bordercolor", "text", "border", "axis", 
  768.    "line1", "line2", "line3",  "line4", 
  769.    "line5", "line6", "line7",  "line8" 
  770.    };
  771. char color_values[Ncolors][30] = { 
  772.    "white", "black",  "black",  "black",  "black", 
  773.    "red",   "green",  "blue",   "magenta", 
  774.    "cyan",  "sienna", "orange", "coral" 
  775.    };
  776. char gray_values[Ncolors][30] = { 
  777.    "black",   "white",  "white",  "gray50", "gray50",
  778.    "gray100", "gray60", "gray80", "gray40", 
  779.    "gray90",  "gray50", "gray70", "gray30" 
  780.    };
  781.  
  782. void pr_color() {
  783.    unsigned long black = BlackPixel(dpy, scr), white = WhitePixel(dpy,scr);
  784.    char option[20], color[30], *v, *type; 
  785.    XColor xcolor;
  786.    Colormap cmap;
  787.    double intensity = -1;
  788.    int n;
  789.  
  790.    pr_GetR(db, ".mono")         && On(value.addr) && Mono++;
  791.    pr_GetR(db, ".gray")         && On(value.addr) && Gray++;
  792.    pr_GetR(db, ".reverseVideo") && On(value.addr) && Rv++;
  793.  
  794.    if (!Gray && (vis->class == GrayScale || vis->class == StaticGray)) Mono++;
  795.  
  796.    if (!Mono) {
  797.       cmap = DefaultColormap(dpy, scr);
  798.       type = (Gray) ? "Gray" : "Color";
  799.  
  800.       for (n=0; n<Ncolors; n++) {
  801.      strcpy(option, ".");
  802.      strcat(option, color_keys[n]);
  803.      (n > 1) && strcat(option, type);
  804.      v = pr_GetR(db, option) 
  805.          ? (char *) value.addr
  806.          : ((Gray) ? gray_values[n] : color_values[n]);
  807.  
  808.      if (sscanf(v,"%30[^,],%lf", color, &intensity) == 2) {
  809.         if (intensity < 0 || intensity > 1) {
  810.            fprintf(stderr, "\ngnuplot: invalid color intensity in '%s'\n",
  811.                        color);
  812.            intensity = 1;
  813.            }
  814.         }
  815.      else { 
  816.         strcpy(color, v);
  817.         intensity = 1;
  818.         }
  819.  
  820.      if (!XParseColor(dpy, cmap, color, &xcolor)) {
  821.         fprintf(stderr, "\ngnuplot: unable to parse '%s'. Using black.\n",
  822.                     color);
  823.         colors[n] = black;
  824.         }
  825.      else {
  826.         xcolor.red *= intensity;
  827.         xcolor.green *= intensity;
  828.         xcolor.blue *= intensity;
  829.         if (XAllocColor(dpy, cmap, &xcolor)) {
  830.            colors[n] = xcolor.pixel;
  831.            }
  832.         else {
  833.            fprintf(stderr, "\ngnuplot: can't allocate '%s'. Using black.\n",
  834.                         v);
  835.            colors[n] = black;
  836.            }
  837.         }
  838.      }
  839.       }
  840.    else {
  841.       colors[0] = (Rv) ? black : white ;
  842.       for (n=1; n<Ncolors; n++)  colors[n] = (Rv) ? white : black;
  843.       }
  844.    }
  845.  
  846. /*-----------------------------------------------------------------------------
  847.  *   pr_dashes - determine line dash styles 
  848.  *---------------------------------------------------------------------------*/
  849.  
  850. char dash_keys[Ndashes][10] =   { 
  851.    "border", "axis",
  852.    "line1", "line2", "line3",  "line4", "line5", "line6", "line7",  "line8" 
  853.    };
  854.  
  855. char dash_mono[Ndashes][10] =   { 
  856.    "0", "16",
  857.    "0", "42", "13",  "44", "15", "4441", "42",  "13" 
  858.    };
  859.  
  860. char dash_color[Ndashes][10] =   { 
  861.    "0", "16",
  862.    "0", "0", "0", "0", "0", "0", "0", "0" 
  863.    };
  864.  
  865. void pr_dashes() {
  866.    int n, j, l, ok;
  867.    char option[20], *v; 
  868.    for (n=0; n<Ndashes; n++) {
  869.       strcpy(option, ".");
  870.       strcat(option, dash_keys[n]);
  871.       strcat(option, "Dashes");
  872.       v = pr_GetR(db, option) 
  873.       ? (char *) value.addr
  874.       : ((Mono) ? dash_mono[n] : dash_color[n]);
  875.       l = strlen(v);
  876.       if (l == 1 && *v == '0') {
  877.      dashes[n][0] = (unsigned char)0;
  878.      continue;
  879.      }
  880.       for (ok=0, j=0; j<l; j++) { v[j] >= '1' && v[j] <= '9' && ok++; }
  881.       if (ok != l || (ok != 2 && ok != 4)) {
  882.      fprintf(stderr, "gnuplot: illegal dashes value %s:%s\n", option, v);
  883.      dashes[n][0] = (unsigned char)0;
  884.      continue;
  885.      }
  886.       for(j=0; j<l; j++) {
  887.      dashes[n][j] = (unsigned char) (v[j] - '0');
  888.      }
  889.       dashes[n][l] = (unsigned char)0;
  890.       }
  891.    }
  892.  
  893. /*-----------------------------------------------------------------------------
  894.  *   pr_font - determine font          
  895.  *---------------------------------------------------------------------------*/
  896.  
  897. void pr_font() {
  898.    char *fontname = pr_GetR(db, ".font");
  899.  
  900.    if (!fontname) fontname = FallbackFont;
  901.    font = XLoadQueryFont(dpy, fontname);
  902.    if (!font) {
  903.       fprintf(stderr, "\ngnuplot: can't load font '%s'\n", fontname);
  904.       fprintf(stderr, "gnuplot: using font '%s' instead.\n", FallbackFont);
  905.       font = XLoadQueryFont(dpy, FallbackFont);
  906.       if (!font) {
  907.      fprintf(stderr, "gnuplot: can't load font '%s'\n", FallbackFont);
  908.      fprintf(stderr, "gnuplot: no useable font - X11 aborted.\n");
  909.          exit(1);
  910.      }
  911.       }
  912.    vchar = font->ascent + font->descent;
  913.    }
  914.  
  915. /*-----------------------------------------------------------------------------
  916.  *   pr_geometry - determine window geometry      
  917.  *---------------------------------------------------------------------------*/
  918.  
  919. void pr_geometry() {
  920.    char *geometry = pr_GetR(db, ".geometry");
  921.    int x, y, flags;
  922.    unsigned int w, h; 
  923.  
  924.    if (geometry) {
  925.       flags = XParseGeometry(geometry, &x, &y, &w, &h);
  926.       if (flags & WidthValue)  User_Size = 1, W = w;
  927.       if (flags & HeightValue) User_Size = 1, H = h;
  928.       if (flags & XValue) {
  929.          if (flags & XNegative)
  930.             x += DisplayWidth(dpy,scr) - W - BorderWidth*2;
  931.          User_Position = 1, gX = x;
  932.          }
  933.       if (flags & YValue) {
  934.          if (flags & YNegative)
  935.             y += DisplayHeight(dpy,scr) - H - BorderWidth*2;
  936.          User_Position = 1, gY = y;
  937.          }
  938.       }
  939.    }
  940.  
  941. /*-----------------------------------------------------------------------------
  942.  *   pr_pointsize - determine size of points for 'points' plotting style
  943.  *---------------------------------------------------------------------------*/
  944.  
  945. void pr_pointsize() {
  946.     if (pr_GetR(db, ".pointsize")) {
  947.     if (sscanf( (char *) value.addr,"%lf", &pointsize) == 1) {
  948.         if (pointsize <= 0 || pointsize > 10) {
  949.         fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", value.addr);
  950.         pointsize = 1;
  951.         }
  952.     } else { 
  953.         fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", value.addr);
  954.         pointsize = 1;
  955.     }
  956.     } else {
  957.         pointsize=1;
  958.     }
  959. }
  960.  
  961. /*-----------------------------------------------------------------------------
  962.  *   pr_width - determine line width values
  963.  *---------------------------------------------------------------------------*/
  964.  
  965. char width_keys[Nwidths][30] =   { 
  966.    "border", "axis",
  967.    "line1", "line2", "line3",  "line4", "line5", "line6", "line7",  "line8" 
  968.    };
  969.  
  970. void pr_width() {
  971.    int n;
  972.    char option[20], *v; 
  973.    for (n=0; n<Nwidths; n++) {
  974.       strcpy(option, ".");
  975.       strcat(option, width_keys[n]);
  976.       strcat(option, "Width");
  977.       if (v = pr_GetR(db, option)) {
  978.      if ( *v < '0' || *v > '4' || strlen(v) > 1)
  979.         fprintf(stderr, "gnuplot: illegal width value %s:%s\n", option, v);
  980.      else 
  981.         widths[n] = (unsigned int)atoi(v);
  982.      }
  983.       }
  984.    }
  985.  
  986. /*-----------------------------------------------------------------------------
  987.  *   pr_window - create window 
  988.  *---------------------------------------------------------------------------*/
  989.  
  990. void pr_window() {
  991.    char *title =  pr_GetR(db, ".title");
  992.    static XSizeHints hints;
  993.    int Tvtwm = 0;
  994.  
  995.    win = XCreateSimpleWindow(dpy, root, gX, gY, W, H, BorderWidth,
  996.                              colors[1], colors[0]);
  997.  
  998.    pr_GetR(db, ".clear") && On(value.addr) && Clear++;
  999.    pr_GetR(db, ".tvtwm") && On(value.addr) && Tvtwm++;
  1000.  
  1001.    if (!Tvtwm) {
  1002.       hints.flags = (User_Position ? USPosition : PPosition);
  1003.       hints.flags |= (User_Size ? USSize : PSize);
  1004.       }
  1005.    else {
  1006.       hints.flags = PPosition;
  1007.       }
  1008.    hints.x = gX; hints.y = gY;        
  1009.    hints.width = W; hints.height = H;
  1010.  
  1011.    XSetNormalHints(dpy, win, &hints);
  1012.  
  1013.    if (pr_GetR(db, ".iconic") && On(value.addr)) {
  1014.       XWMHints wmh;
  1015.  
  1016.       wmh.flags = StateHint ;
  1017.       wmh.initial_state = IconicState;
  1018.       XSetWMHints(dpy, win, &wmh);
  1019.       } 
  1020.  
  1021.    XStoreName(dpy, win, ((title) ? title : Class));
  1022.  
  1023.    XSelectInput(dpy, win, StructureNotifyMask);
  1024.    XMapWindow(dpy, win);
  1025.    
  1026.    }
  1027.